﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using DataServer.Extend;
using log4net.Core;

namespace DataServer.View
{
    /// <summary>
    /// MsgPanel.xaml 的交互逻辑
    /// </summary>
    public partial class LogView
    {
        private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
       
        private readonly LogMemAppender logger = new LogMemAppender();
        private readonly ObservableCollection<LogContent> logContents = new ObservableCollection<LogContent>();
        private readonly List<LogContent> backupLogContents = new List<LogContent>();
        private readonly object _synObj = new object();
        private readonly List<MenuItem> menuItems = new List<MenuItem>();

        public LogView()
        {
            InitializeComponent();
            Loaded += LogPanel_Loaded;
            Unloaded += LogPanel_Unloaded;
            this.DataContext = logContents;
            log4net.Config.BasicConfigurator.Configure(logger);
            logger.OnReceiveEvent += Logger_OnReceiveEvent;
        }

        private void Logger_OnReceiveEvent(LoggingEvent evt)
        {
            this.Dispatcher.BeginInvoke(new Action((() =>
            {
                //string line = (evt.LocationInformation == null || evt.LocationInformation == null)
                //    ? "  [" + evt.LoggerName + "]"
                //    : $"  [Class:{evt.LocationInformation.ClassName}--Line:{evt.LocationInformation.LineNumber} ]";
                //string content = evt.RenderedMessage + line;
                LogContent logContent = new LogContent(evt.Level, evt.TimeStamp, evt.RenderedMessage);
                AppendLog(logContent);
            })));
        }

        private void LogPanel_Unloaded(object sender, RoutedEventArgs e)
        {
           
        }

        private void LogPanel_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                menuItems.Clear();
                menuItems.AddRange(new []{miAllLog,miErrorLog,miWarningLog,miInforLog,miDebugLog});
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
            }
            
        }
        private void AppendLog(LogContent log)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                lock (_synObj)
                {
                    if (logContents.Count > 500)
                    {
                        logContents.RemoveAt(0);
                    }
                    else
                    {
                        if(miAllLog.IsChecked)
                            logContents.Add(log);
                        else if(miErrorLog.IsChecked && log.Level== Level.Error)
                            logContents.Add(log);
                        else if (miWarningLog.IsChecked && log.Level == Level.Warn)
                            logContents.Add(log);
                        else if (miInforLog.IsChecked && log.Level == Level.Info)
                            logContents.Add(log);
                        else if (miDebugLog.IsChecked && log.Level == Level.Debug)
                            logContents.Add(log);
                    }
                    if (backupLogContents.Count > 500)
                    {
                        backupLogContents.RemoveAt(0);
                    }
                    else
                    {
                        backupLogContents.Add(log);
                    }
                    
                    if (txtLogger.Items.Count > 0 && !frozenMenuItem.IsChecked)
                    {
                        txtLogger.ScrollIntoView(txtLogger.Items[txtLogger.Items.Count - 1]);
                    }
                }
            }));
        }
        private void ClearLogMsg_OnClick(object sender, RoutedEventArgs e)
        {
            lock (_synObj)
            {
                logContents.Clear();
                backupLogContents.Clear();
            }
        }

        private void FrozenLogMsg_OnClick(object sender, RoutedEventArgs e)
        {
            frozenMenuItem.IsChecked = !frozenMenuItem.IsChecked;
        }

       
        private void MiAllLog_OnChecked(object sender, RoutedEventArgs e)
        {
            lock (_synObj)
            {
                foreach (MenuItem item in menuItems)
                {
                    if (sender.Equals(item))
                    {
                        if(!item.IsChecked)
                            item.IsChecked = true;
                    }
                    else
                    {
                        item.IsChecked = false;
                    }
                }
                logContents.Clear();
                if (miAllLog.IsChecked)
                {
                    foreach (LogContent content in backupLogContents)
                    {
                        logContents.Add(content);
                    }
                }
                else if (miErrorLog.IsChecked)
                {
                    foreach (LogContent content in backupLogContents)
                    {
                        if(content.Level== Level.Error)
                            logContents.Add(content);
                    }
                }
                else if (miWarningLog.IsChecked)
                {
                    foreach (LogContent content in backupLogContents)
                    {
                        if (content.Level == Level.Warn)
                            logContents.Add(content);
                    }
                }
                else if (miInforLog.IsChecked)
                {
                    foreach (LogContent content in backupLogContents)
                    {
                        if (content.Level == Level.Info)
                            logContents.Add(content);
                    }
                }
                else if (miDebugLog.IsChecked)
                {
                    foreach (LogContent content in backupLogContents)
                    {
                        if (content.Level == Level.Debug)
                            logContents.Add(content);
                    }
                }
            }
            
        }
    }

    public class LogContent
    {
        public Level Level { get; set; }
        public DateTime Time { get; set; }
        public string Content { get; set; }

        public LogContent(Level level,DateTime time,string content)
        {
            Level = level;
            Time = time;
            Content = content;
        }
    }
    
}
